package com.ruoyi.app.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.aliyun.oss.ServiceException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.app.dao.SigInMapper;
import com.ruoyi.app.dao.UserAuthMapper;
import com.ruoyi.app.dao.UserMapper;
import com.ruoyi.app.dao.UserTaskMapper;
import com.ruoyi.app.entity.SignIn;
import com.ruoyi.app.entity.User;
import com.ruoyi.app.entity.UserAuth;
import com.ruoyi.app.entity.UserTask;
import com.ruoyi.app.model.vo.*;
import com.ruoyi.app.service.SmsService;
import com.ruoyi.app.service.UserService;
import com.ruoyi.common.context.ApiUserContext;
import com.ruoyi.common.utils.JwtTokenUtil;
import com.ruoyi.common.utils.security.Md5Utils;
import com.xkzhangsan.time.formatter.DateTimeFormatterUtil;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.util.Asserts;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


@Service
@Slf4j
public class UserServiceImpl implements UserService {


    @Autowired
    private UserMapper userMapper;

    @Autowired
    private SmsService smsService;

    @Autowired
    private SigInMapper sigInMapper;

    @Autowired
    private UserAuthMapper userAuthMapper;

    @Autowired
    private UserTaskMapper userTaskMapper;

    @Override
    public RegisterRes register(RegisterReq req) {

        User user = userMapper.selectByPhone(req.getPhone());
        Assert.isNull(user, "手机号已存在！");

        user = new User();
        user.setPhone(req.getPhone());
        user.setSex(req.getSex());
        user.setPicture(JSON.toJSONString(new ArrayList<>()));
        user.setMember(0);
        userMapper.insert(user);


        UserAuth userAuth = new UserAuth();
        userAuth.setUserId(user.getId());
        userAuth.setRealCarState(0);
        userAuth.setRealHouseState(0);
        userAuth.setRealNameState(0);
        userAuthMapper.insert(userAuth);


        UserTask userTask = new UserTask();
        userTask.setUserId(user.getId());
        userTask.setSignTask(0);
        userTask.setBindingPhone(0);
        userTask.setBindingWx(0);
        userTask.setSupplementData(0);
        userTask.setReleaseNews(0);
        userTask.setAuthName(0);
        userTask.setAuthHouse(0);
        userTask.setAuthCar(0);
        userTaskMapper.insert(userTask);

        return new RegisterRes(user.getId(), JwtTokenUtil.buildJWT(user.getId()));
    }


    @Override
    public LoginRes login(LoginReq req) {
        User user = userMapper.selectByPhone(req.getPhone());
        Assert.notNull(user, "手机号未注册！");
        if (req.getType() == 0) {
            // 密码登录
            Assert.hasText(user.getPwd(), "该账户还未设置登录密码，请设置密码后再登录！");
            Assert.isTrue(user.getPwd().equals(Md5Utils.hash(req.getVoucher())), "密码输入错误！");
        } else {
            // 验证码登录
            smsService.verifyCode(req.getPhone(), req.getVoucher());
        }

        return new LoginRes(user.getId(), JwtTokenUtil.buildJWT(user.getId()), !StringUtils.isEmpty(user.getPwd()));
    }


    @Override
    public GetUserInfoRes getUserInfo() {
        String userId = ApiUserContext.getLocalUser().getUserId();
        User user = userMapper.selectById(userId);

        GetUserInfoRes res = new GetUserInfoRes();

        GetUserInfoRes.BasicInformation basicInformation = new GetUserInfoRes.BasicInformation();
        BeanUtil.copyProperties(user, basicInformation);
        res.setBasicInfo(basicInformation);

        GetUserInfoRes.MateIntention mateIntention = new GetUserInfoRes.MateIntention();
        BeanUtil.copyProperties(user, mateIntention);
        res.setMateIntention(mateIntention);

        GetUserInfoRes.MoreInfo moreInfo = new GetUserInfoRes.MoreInfo();
        BeanUtil.copyProperties(user, moreInfo);
        res.setMoreInfo(moreInfo);

        UserAuth userAuth = userAuthMapper.selectById(userId);
        if (ObjectUtils.isEmpty(userAuth)) {
            res.setAuthInfo(new GetUserInfoRes.AuthInfo(0, 0, 0));
        } else {
            GetUserInfoRes.AuthInfo authInfo = new GetUserInfoRes.AuthInfo();
            BeanUtil.copyProperties(userAuth, authInfo);
            res.setAuthInfo(authInfo);
        }

        return res;
    }


    @Override
    public ModifyUserInfoRes modifyUserInfo(ModifyUserInfoReq req) {
        String userId = ApiUserContext.getLocalUser().getUserId();
        User user = new User();
        user.setId(userId);
        BeanUtils.copyProperties(req, user);
        ModifyUserInfoRes modifyUserInfoRes = new ModifyUserInfoRes(userMapper.updateById(user) > 0);

        // 手机号是否完善
        if (!StringUtils.isEmpty(req.getPhone())) {

            // todo sdf
        }


        return modifyUserInfoRes;
    }


    @Override
    public Object modifyUserPwd(ModifyUserPwdReq req) {
        String userId = ApiUserContext.getLocalUser().getUserId();
        User user = userMapper.selectById(userId);
        if (!StringUtils.isEmpty(user.getPwd())) {
            if (StringUtils.isEmpty(req.getOldPwd())) {
                throw new IllegalArgumentException("请输入原密码！");
            }

            if (!user.getPwd().equals(Md5Utils.hash(req.getOldPwd()))) {
                throw new IllegalArgumentException("原密码输入错误！");
            }
        }


        User upUser = new User();
        upUser.setId(userId);
        upUser.setPwd(Md5Utils.hash(req.getNewPwd()));
        return userMapper.updateById(upUser) > 0;
    }


    @Override
    public Object modifyUserPhone(ModifyUserPhoneReq req) {
        String userId = ApiUserContext.getLocalUser().getUserId();

        // 验证码登录
        smsService.verifyCode(req.getPhone(), req.getCode());

        User user = userMapper.selectByPhone(req.getPhone());
        Assert.isNull(user, "手机号已存在！");

        User upUser = new User();
        upUser.setId(userId);
        upUser.setPhone(req.getPhone());
        return userMapper.updateById(upUser) > 0;
    }


    @Override
    public Object signIn() {
        String userId = ApiUserContext.getLocalUser().getUserId();
        SignIn sigIn = sigInMapper.queryUserDate(userId, DateUtil.formatDate(new Date()));
        Assert.isNull(sigIn, "今日已签到！");
        sigIn = new SignIn();
        sigIn.setUserId(userId);
        sigInMapper.insert(sigIn);


        UserTask userTask = userTaskMapper.selectById(userId);
        if (userTask.getSignTask() == 0) {
            int signNumber = calculateSignIn(userId, new Date());
            if (signNumber >= 6) {
                // 以连续签到七天
                userTask.setSignTask(1);
                userTaskMapper.updateById(userTask);
                // todo 连续签到  获得七天会员
                System.out.println("连续签到增加 获得七天会员");
            }
        }

        return true;
    }


    @Override
    public Object delAccount(String account) {
        User user = userMapper.selectByPhone(account);
        if (user != null) {
            userMapper.deleteById(user.getId());
        }
        return true;
    }


    @Override
    public TaskListRes taskList() {
        TaskListRes res = new TaskListRes();
        String userId = ApiUserContext.getLocalUser().getUserId();

        UserTask userTask = userTaskMapper.selectById(userId);
        if (userTask != null) {
            BeanUtils.copyProperties(userTask, res);
        }

        // 计算连续签到天数
        int signDay = 0;
        SignIn nowSigIn = sigInMapper.queryDate(userId, DateUtil.formatDate(new Date()));
        if (nowSigIn == null) {

            DateTime dateTime = DateUtil.offsetDay(new Date(), -1);
            SignIn dayBeforeSigIn = sigInMapper.queryDate(userId, DateTimeFormatterUtil.format(dateTime, "yyyy-MM-dd"));
            if (dayBeforeSigIn != null) {
                signDay++;
                signDay = signDay + calculateSignIn(userId, Date.from(dayBeforeSigIn.getCreateTime().atZone(ZoneId.systemDefault()).toInstant()));
            }
        } else {
            signDay++;
            signDay = signDay + calculateSignIn(userId, Date.from(nowSigIn.getCreateTime().atZone(ZoneId.systemDefault()).toInstant()));
        }

        res.setSignDay(signDay);
        return res;
    }


    @Override
    public Object modifyUserAuth(ModifyUserRealNameReq req) {
        String userId = ApiUserContext.getLocalUser().getUserId();

        UserAuth userAuth = userAuthMapper.selectById(userId);

        // 认证类型 0：实名认证 1：房屋认证 2：车辆认证
        if (req.getType().equals("0")) {

            if (userAuth.getRealNameState() != 0 && userAuth.getRealNameState() != 2) {
                throw new IllegalArgumentException("当前状态不允许提交审核！");
            }
            userAuth.setRealNameState(1);
            userAuth.setRealNameStatePic(req.getPicture());

        } else if (req.getType().equals("1")) {

            if (userAuth.getRealHouseState() != 0 && userAuth.getRealHouseState() != 2) {
                throw new IllegalArgumentException("当前状态不允许提交审核！");
            }
            userAuth.setRealHouseState(1);
            userAuth.setRealHouseStatePic(req.getPicture());

        } else {

            if (userAuth.getRealCarState() != 0 && userAuth.getRealCarState() != 2) {
                throw new IllegalArgumentException("当前状态不允许提交审核！");
            }
            userAuth.setRealCarState(1);
            userAuth.setRealCarStatePic(req.getPicture());
        }

        return userAuthMapper.updateById(userAuth);
    }


    @Override
    public List<IndexPageRes> indexPage(IndexPageReq req) {
        String userId = "";
        try {
            userId = ApiUserContext.getLocalUser().getUserId();
        } catch (Exception e) {
            log.info("首页用户未登录访问");
        }
        Page page = new Page<>(req.getNowPage(), req.getPageSize());

        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper();
        if (!StringUtils.isEmpty(userId)) {
            queryWrapper.ne(User::getId, userId);
        }

        IPage<User> userList = userMapper.selectPage(page, queryWrapper);
        List<User> users = userList.getRecords();

        List<IndexPageRes> list = users.stream().map(user -> {
            IndexPageRes indexPageRes = new IndexPageRes();

            BeanUtil.copyProperties(user, indexPageRes);
            return indexPageRes;
        }).collect(Collectors.toList());
        return list;
    }


    @Override
    public Object userInfo(UserInfoReq req) {
        String loginUserId = ApiUserContext.getLocalUser().getUserId();
        User loginUser = userMapper.selectById(loginUserId);
        if (loginUser.getMember() == 0) {
            throw new IllegalArgumentException("非会员不可查看，请充值会员！");
        }

        User user = userMapper.selectById(req.getUserId());
        UserInfoRes res = new UserInfoRes();
        BeanUtil.copyProperties(user, res);

        UserAuth userAuth = userAuthMapper.selectById(user.getId());
        if (userAuth.getRealNameState() == 3) {
            res.setRealNameState("1");
        }

        if (userAuth.getRealHouseState() == 3) {
            res.setRealHouseState("1");
        }

        if (userAuth.getRealCarState() == 3) {
            res.setRealCarState("1");
        }
        return res;
    }


    /**
     * 今日是否签到
     *
     * @return
     */
    @Override
    public Object signToday() {
        String userId = ApiUserContext.getLocalUser().getUserId();
        SignIn current = sigInMapper.queryDate(userId, DateTimeFormatterUtil.format(new Date(), "yyyy-MM-dd"));
        return ObjectUtil.isNotNull(current);
    }


    /**
     * 计算签到天数
     *
     * @param userId 用户标识
     * @param date   2020-01-01
     * @return
     */
    public int calculateSignIn(String userId, Date date) {
        int number = 0;

        while (true) {
            DateTime dateTime = DateUtil.offsetDay(date, -1);
            SignIn current = sigInMapper.queryDate(userId, DateTimeFormatterUtil.format(dateTime, "yyyy-MM-dd"));
            if (current == null) {
                break;
            }

            date = dateTime;
            number++;
        }
        return number;
    }


    public static void main(String[] args) {
        System.out.println(Duration.ofSeconds(10L));
    }


}
